package com.atguigu.gmall.realtime.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.flink.api.java.tuple.Tuple2;
import redis.clients.jedis.Jedis;

import java.util.List;

/**
 * Author: Felix
 * Date: 2022/4/9
 * Desc: 查询维度数据的工具类
 */
public class DimUtil {

    public static JSONObject getDimInfo(String tableName, String id) {
        return getDimInfo(tableName, Tuple2.of("ID", id));
    }

    /**
     * @param tableName                 维度表名
     * @param columnNameAndColumnValues 查询条件
     * @return 维度对象
     * 查询维度数据  使用旁路缓存进行优化
     * 思路：先从缓存Redis中查询维度数据，如果从缓存中查询到了维度数据，直接将维度数据返回（缓存命中）
     * 如果从缓存中没有查询到维度数据，再发送请求到phoenix表中查询维度，并将查询的结果放到Redis中缓存起来
     * 分析：
     * Redis类型：String      Key: dim:维度表表名:主键值1_主键值2    expire:1day
     */
    public static JSONObject getDimInfo(String tableName, Tuple2<String, String>... columnNameAndColumnValues) {
        //拼接从Redis中查询维度数据的key
        StringBuilder redisKey = new StringBuilder("dim:" + tableName.toLowerCase() + ":");
        //拼接查询维度的SQL
        StringBuilder selectDimSql = new StringBuilder("select * from " + tableName + " where ");
        for (int i = 0; i < columnNameAndColumnValues.length; i++) {
            Tuple2<String, String> columnNameAndColumnValue = columnNameAndColumnValues[i];
            String columnName = columnNameAndColumnValue.f0;
            String columnValue = columnNameAndColumnValue.f1;

            redisKey.append(columnValue);
            selectDimSql.append(columnName + " = '" + columnValue + "' ");
            if (i < columnNameAndColumnValues.length - 1) {
                redisKey.append("_");
                selectDimSql.append(" and ");
            }
        }

        Jedis jedis = null;
        String dimJsonStr = null;
        JSONObject dimJsonObj = null;

        try {
            jedis = RedisUtil.getJedis();
            dimJsonStr = jedis.get(redisKey.toString());
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("从Redis中获取维度数据失败");
        }

        //判断是否从Redis缓存中获取到了维度数据
        if (dimJsonStr != null && dimJsonStr.length() > 0) {
            //缓存命中  将查询到json字符串转换为json对象
            dimJsonObj = JSON.parseObject(dimJsonStr);
        } else {
            //从Redis缓存中，没有查到维度数据，发送请求到phoenix表中进行查询
            System.out.println("从Phoenix表中查询维度的SQL为:" + selectDimSql);
            //底层还是调用PhoenixUtil工具类
            List<JSONObject> dimList = PhoenixUtil.queryList(selectDimSql.toString(), JSONObject.class);
            if (dimList != null && dimList.size() > 0) {
                //说明在维度表中查到了维度数据，因为是根据主键查询的，list中只会返回一条数据
                dimJsonObj = dimList.get(0);
                //将查询结果放到Redis中缓存起来
                if (jedis != null) {
                    jedis.setex(redisKey.toString(), 3600 * 24, dimJsonObj.toJSONString());
                }
            } else {
                System.out.println("维度数据没找到:" + selectDimSql);
            }
        }

        if (jedis != null) {
            System.out.println("~~~关闭Jedis客户端~~~");
            jedis.close();
        }

        return dimJsonObj;
    }

    //专门查询维度数据的方法，维度是通过主键进行查询，不会有多条数据，所以我们统计将维度封装JSONObject
    public static JSONObject getDimInfoNoCache(String tableName, Tuple2<String, String>... columnNameAndColumnValues) {
        //拼接查询维度的SQL
        StringBuilder selectDimSql = new StringBuilder("select * from " + tableName + " where ");
        for (int i = 0; i < columnNameAndColumnValues.length; i++) {
            Tuple2<String, String> columnNameAndColumnValue = columnNameAndColumnValues[i];
            String columnName = columnNameAndColumnValue.f0;
            String columnValue = columnNameAndColumnValue.f1;

            selectDimSql.append(columnName + " = '" + columnValue + "' ");
            if (i < columnNameAndColumnValues.length - 1) {
                selectDimSql.append(" and ");
            }
        }

        System.out.println("从Phoenix表中查询维度的SQL为:" + selectDimSql);

        //底层还是调用PhoenixUtil工具类
        JSONObject dimJsonObj = null;
        List<JSONObject> dimList = PhoenixUtil.queryList(selectDimSql.toString(), JSONObject.class);
        if (dimList != null && dimList.size() > 0) {
            //说明在维度表中查到了维度数据，因为是根据主键查询的，list中只会返回一条数据
            dimJsonObj = dimList.get(0);
        } else {
            System.out.println("维度数据没找到:" + selectDimSql);
        }
        return dimJsonObj;
    }

    //从Redis中删除已经缓存的维度数据
    public static void deleteCached(String tableName,String id){
        String redisKey = "dim:" + tableName.toLowerCase() + ":" + id;
        Jedis jedis = null;
        try {
            jedis = RedisUtil.getJedis();
            jedis.del(redisKey);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            jedis.close();
        }
    }

    public static void main(String[] args) {
        //JSONObject dimInfoJsonObj = getDimInfoNoCache("dim_base_trademark",Tuple2.of("ID","17"));
        //JSONObject dimInfoJsonObj = getDimInfo("dim_base_trademark", Tuple2.of("ID", "17"));
        JSONObject dimInfoJsonObj = getDimInfo("dim_base_trademark", "17");
        System.out.println(dimInfoJsonObj);
    }
}
